#!/usr/bin/env python
# -*- coding: latin-1; py-indent-offset:4 -*-
################################################################################
# 
# This file is part of Bfplusplus
#
# Bfplusplus is a graphical interface to the Betfair Betting Exchange
# Copyright (C) 2010 Daniel Rodriguez (aka Daniel Rodriksson)
# Copyright (C) 2011 Sensible Odds Ltd.
#
# You can learn more and contact the author at:
#
#    http://code.google.com/p/bfplusplus/
#
# Bfplusplus is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Bfplusplus is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Bfplusplus. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""Subclass of RunnerAction, which is generated by wxFormBuilder."""

from collections import defaultdict

import wx
# The first import is eeded for version 3 of the pubsub api (simpler management)
from wx.lib.pubsub import setupkwargs
from wx.lib.pubsub import pub

import MainGui

from util import Message, splitThousands

class LadderPrice(object):
    def __init__(self):
        self.totalAvailableBackAmount = 0.0
        self.totalAvailableLayAmount = 0.0
        self.totalMatchedAmount = 0.0


# Implementing RunnerAction
class RunnerAction(MainGui.RunnerAction):
    def __init__(self, parent):
	MainGui.RunnerAction.__init__(self, parent)

	pub.subscribe(self.OnRunnerAction, 'runner.action')
	pub.subscribe(self.OnRunnerActionBitmap, 'runner.actionbitmap')
	pub.subscribe(self.OnRunnerActionTradedVolume, 'runner.actiontradedVolume')
        pub.subscribe(self.OnRunnerActionCompletePrices, 'runner.actioncompletePrices')

	self.myparent = parent
        self.SetIcon(self.myparent.myIcon)

        self.marketComp = None

        self.tradedVolume = None
        self.completePrices = None
        self.pricing = defaultdict(int)

        self.totalMatched = 0.0
        self.totalMatchedRunner = dict()
        self.lastPriceMatched = dict()


    def OnClose(self, event):
	self.myparent.runnerAction = None
	self.Destroy()


    def LoadPricing(self):
        self.pricing.clear()
        self.completePrices = None
        self.tradedVolume = None

        if self.myparent.marketTuple is not None:
            # Reload prices if market has changed
            message = Message(action='runnerActionTradedVolume',
                              marketTuple=self.myparent.marketTuple)
            self.myparent.thMisc.passMessage(message)

            message = Message(action='runnerActionCompletePrices',
                              marketTuple=self.myparent.marketTuple)
            self.myparent.thMisc.passMessage(message)

    
    def OnRunnerAction(self, marketComp, selection):
        if self.marketComp is None or self.marketComp.marketId != marketComp.marketId:
            self.marketComp = marketComp

            self.LoadPricing()

            try:
                menuPath, menuParts = marketComp.getFullMenuPath()
                marketName = '%s - %s' % (menuParts[-2], marketComp.name)
                self.m_staticTextMarketName.SetLabel(marketName)

                self.m_choiceRunners.Clear()
                for runner in marketComp.runners:
                    runnerName = marketComp.getRunnerLabel(runner)
                    self.m_choiceRunners.Append(runnerName)
            except:
                pass

        self.m_choiceRunners.SetSelection(selection)
        self.LoadRunnerData()


    def OnChoiceRunners(self, event):
        self.LoadRunnerData()


    def LoadRunnerData(self):
        selection = self.m_choiceRunners.GetSelection()
        try:
            if self.marketComp.runners:
                runner = self.marketComp.runners[selection]

                message = Message(action='runnerActionBitmap',
                                  marketTuple=self.myparent.marketTuple,
                                  selectionId=runner.selectionId,
                                  asianLineId=runner.asianLineId,
                                  inverseAxis=self.m_checkBoxInverseAxis.GetValue())
                self.myparent.thMisc.passMessage(message)
        except:
            pass

        numRows = self.m_gridPricing.GetNumberRows()
        if numRows > 0:
            self.m_gridPricing.DeleteRows(0, numRows)

        self.m_staticTextTotalMatchedEvent.SetLabel('')
        self.m_staticTextTotalMatchedRunner.SetLabel('')
        self.m_staticTextLastPriceMatched.SetLabel('')

        self.DisplayPricing()


    def OnRunnerActionBitmap(self, imageStream):
        try:
            image = wx.ImageFromStream(imageStream)
            bitmap = wx.BitmapFromImage(image)

            self.m_bitmapRunnerAction.SetBitmap(bitmap)
        except Exception, e:
            pass
	

    def OnRunnerActionTradedVolume(self, tradedVolume):
        self.tradedVolume = tradedVolume

        if self.completePrices:
            self.GeneratePricing()


    def OnRunnerActionCompletePrices(self, completePrices):
        self.completePrices = completePrices

        if self.tradedVolume:
            self.GeneratePricing()


    def GeneratePricing(self):
        self.pricing.clear()

        try:
            for runner in self.marketComp.runners:
                self.pricing[runner.selectionId] = defaultdict(LadderPrice)

            self.totalMatched = 0.0
            for runnerInfo in self.tradedVolume:
                selectionId = runnerInfo.selectionId
                self.totalMatchedRunner[selectionId] = 0.0

                for priceItem in runnerInfo.priceItems:
                    ladderPrice = self.pricing[selectionId][priceItem.odds]
                    ladderPrice.totalMatchedAmount = priceItem.totalMatchedAmount
                    self.totalMatchedRunner[selectionId] += priceItem.totalMatchedAmount

                self.totalMatched += self.totalMatchedRunner[selectionId]

            for runnerInfo in self.completePrices.runnerPrices:
                selectionId = runnerInfo.selectionId

                self.lastPriceMatched[selectionId] = runnerInfo.lastPriceMatched

                for price in runnerInfo.prices:
                    ladderPrice = self.pricing[selectionId][price.odds]
                    ladderPrice.totalAvailableBackAmount = price.totalAvailableBackAmount
                    ladderPrice.totalAvailableLayAmount = price.totalAvailableLayAmount
        except:
            pass
        self.DisplayPricing()


    def DisplayPricing(self):
        if self.pricing:
            selection = self.m_choiceRunners.GetSelection()
            if not self.marketComp.runners:
                self.m_staticTextTotalMatchedEvent.SetLabel('')
                self.m_staticTextTotalMatchedRunner.SetLabel('')
                self.m_staticTextLastPriceMatched.SetLabel('')
                return

            try:
                runner = self.marketComp.runners[selection]

                ladderPrices = self.pricing[runner.selectionId]
                self.m_gridPricing.AppendRows(len(ladderPrices))
                odds = ladderPrices.keys()
                odds.sort()
                for row, price in enumerate(odds):
                    toBack = ladderPrices[price].totalAvailableBackAmount
                    toLay = ladderPrices[price].totalAvailableLayAmount
                    traded = ladderPrices[price].totalMatchedAmount

                    self.m_gridPricing.SetRowLabelValue(row, '%.2f' % price)
                    if toBack:
                        self.m_gridPricing.SetCellValue(row, 0, '%.2f' % toBack)
                    if toLay:
                        self.m_gridPricing.SetCellValue(row, 1, '%.2f' % toLay)
                    if traded:
                        self.m_gridPricing.SetCellValue(row, 2, '%.2f' % traded)

                self.m_staticTextTotalMatchedEvent.SetLabel(splitThousands(int(self.totalMatched)))
                self.m_staticTextTotalMatchedRunner.SetLabel(splitThousands(int(self.totalMatchedRunner[runner.selectionId])))
                self.m_staticTextLastPriceMatched.SetLabel('%.2f' % self.lastPriceMatched[runner.selectionId])
            except:
                pass

    def OnButtonClickReloadData(self, event):
        event.Skip()
        self.pricing.clear()
        self.LoadRunnerData()
        self.LoadPricing()


    def OnCheckBoxInverseAxis(self, event):
        event.Skip()
        self.LoadRunnerData()

